/**************************************************************************/
/*  Copyright (C) School of Software Engineering of USTC, 2013             
/*                                                                        
/*  FILE NAME: WordSeg.cpp                                                  
/*  PRINCIPAL AUTHOR: SA12226340(Song Zeyu)                                                                                                          
/*  LANGUAGE: C/C++                                                          
/*  TARGET ENVIRONMENT: Linux                                             
/*  DATE OF FIRST RELEASE: 2013-05-13                                    
/*  DESCRIPTION:extract word segmentation to  every spam, the results stored 
/*              in the map ,map format:<string,int>                      
/**************************************************************************/

#include "Dictionary.h"
#include "MyMap.h"
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
using namespace std;

#define MaxWordLength 30 //max length of word
CDictionary WordDic;

/*
*file list,all the file's name of the folder stores in the list
*/
struct FileList
{
	char file_path[64];
    struct FileList *next;
}start,*node;


/*****************************************************************
Function Name: WordMap
Description: implement the string should insert the map or discard
Parameter:  
@str: a pointer to string needed to find whether or not stored in the map 
@map_nodes: a Parameter to the str Where should look for in a map?

Author: SA12226340(Song Zeyu)
Date: 2013-05-13
******************************************************************/
void WordsMap(char *str,int map_nodes)
{
	FindMapWord(str,map_nodes);
}


/*****************************************************************
Function Name: SegmentSentence
Description: implement word segmentation for str and the word should insert the map_nodes map
Parameter:  
@str: a pointer to string needed to extract word segmentation  
@map_nodes: a Parameter to the str should insert in the map_nodes map

Author: SA12226340(Song Zeyu)
Date: 2013-05-13
******************************************************************/
void SegmentSentence(char *str,int map_nodes)
{
	int ini_len=strlen(str);
	char * s1=(char *)malloc(ini_len+1);
	strcpy(s1,str);                                 //the Parameter copy the Temporary variable s1

	char *word_buf=(char *)malloc(ini_len);
	while(strlen(s1)!=0)                            //string is not null
	{
		memset(word_buf,0,ini_len);                 //initializion 0
		int len = strlen(s1); 
		
		if (len > MaxWordLength)                    //length of string > MaxWordLength 
		{
			len = MaxWordLength; 
		}
		
		strncpy(word_buf,s1+strlen(s1)-len,len);    //Take the final len bytes's word
		int n = WordDic.FindWord(word_buf);         // find word_buf word in WordDic	
		while(len > 3 && n == 0)                    //not find word_buf and len >3,one Chinese characters has three Byte
		{
			len -= 3; 
			memset(word_buf,0,ini_len);
			strncpy(word_buf,s1+strlen(s1)-len,len);//if the not find,then remove the first Chinese characters of the word
			n = WordDic.FindWord(word_buf);         //find word_buf word in WordDic	
		}	
		/*
		*if the word_buf can find in WordDic, then insert the word_buf into the map_nodes map
		*/
		if (n==1)
		{
			WordsMap(word_buf,map_nodes);
		}
		strncpy(word_buf,s1,strlen(s1)-len);        //discard the lastest len char
		
		if((strlen(s1)-len)!=0)
		{
			strcpy(s1,word_buf);
		}
		else
		{	
			memset(s1,0,strlen(s1));
		}
	}
	free(s1);
	free(word_buf);
}

/*****************************************************************
Function Name: SegmentSentenceMM
Description: implement word segmentation for str and the word should insert the map_nodes map
Parameter:  
@str: a pointer to string needed to extract word segmentation  
@map_nodes: a Parameter to the str should insert in the map_nodes map

Author: SA12226340(Song Zeyu)
Date: 2013-05-13
******************************************************************/
void SegmentSentenceMM (char *str,int map_nodes)
{
	int i;
	int dd;
	int ini_len=strlen(str);
	char *s1=(char *)malloc(ini_len+1);
	strcpy(s1,str);
	char * tmp=(char *)malloc(ini_len+1);

	while(strlen(s1) != 0)
	{
		unsigned char ch = (unsigned char)s1[0];
		if (ch < 128)                               // English punctuation
		{
			i = 1;
			dd = strlen(s1);
			while (i < dd && ((unsigned char)s1[i] < 128) && (s1[i] != 10) && (s1[i] != 13)) //LR ,CF.Line breaks and spaces
			{
				i++;
			}
			strncpy(tmp,s1+i,dd);
			strcpy(s1,tmp);
			continue;
		}
		else
		{
			if (ch < 176)                           // chinese punctuation
			{
				i = 0;
				dd = strlen(s1);
				while(i < dd && ((unsigned char)s1[i] < 176) && ((unsigned char)s1[i] >= 161)
					&& (!((unsigned char)s1[i] == 161 && ((unsigned char)s1[i+1] >= 162 && (unsigned char)s1[i+1] <= 168)))
					&& (!((unsigned char)s1[i] == 161 && ((unsigned char)s1[i+1] >= 171 && (unsigned char)s1[i+1] <= 191)))
					&& (!((unsigned char)s1[i] == 163 && ((unsigned char)s1[i+1] == 172 || (unsigned char)s1[i+1] == 161)
					|| (unsigned char)s1[i+1] == 168 || (unsigned char)s1[i+1] == 169 || (unsigned char)s1[i+1] == 186
					|| (unsigned char)s1[i+1] == 187 || (unsigned char)s1[i+1] == 191)))
				{
					i = i + 3;                      // Each character three bytes
				}
				if (i == 0)
				{
					i = i +3;
				}
				strncpy(tmp,s1+i,dd);
				strcpy(s1,tmp);
				continue;
			}
		}
		i = 3;
		dd = strlen(s1);
		while(i < dd && (unsigned char)s1[i] >= 176)
		{
			i += 3;                                 //the length of s1 string with out punctuation marks
		}
		memset(tmp,0,ini_len+1);
		memcpy(tmp,s1,i);                           // s1 string removes the punctuation marks
		SegmentSentence(tmp,map_nodes);
		strncpy(tmp,s1+i,dd);                       //s1 string move backward
		strcpy(s1,tmp);
	}
	free(s1);
	free(tmp);
}
int main(int argc,char **argv )
{
	/*
	*Initialization,include file directory,FILE pointer,buffer
	*/
	DIR *directory_pointer;                         //define a folder directory pointer to folder
	struct dirent *entry;                           //in order to obtain a folder structure of the contents of a directory
	FILE *fp = NULL;
	char buffer[256] = {'\0'};
	int file_nodes = 0;                             //the index file stores into the index mapword		 			
	/*
	*when input is folder,Execution: ./WordSeg test
	*/
	if (argc!=2)
	{
		printf("Must specify a directory\n");
    	exit(1);
  	}
  	
	if ((directory_pointer=opendir(argv[1]))==NULL)
    	printf("Error opening %s\n",argv[1]);
    else
	{
		start.next=NULL;
		node=&start;
		while ((entry=readdir(directory_pointer))!=NULL)
    	{
    		if(strcmp(entry->d_name,".")!=0 && strcmp(entry->d_name,"..")!=0)
    		{
    			char path[50]="./test/";            //Relative paths,
      			node->next=(struct FileList *)malloc(sizeof(struct FileList));
      			node=node->next;
      			node->next = NULL;
      			strcpy(node->file_path,entry->d_name); //entry->d_name means file name
      			strcat(path,node->file_path);
      			strcpy(node->file_path,path);       //node->file_path means file the absolute path
    		}   		
    	}
		closedir(directory_pointer);
		/*
		*for test,output all file of file_path
		*/
		node=start.next;
		while(node)
    	{
      		printf("%s\n",node->file_path);
      		node=node->next;
    	}
  	}
  	node = start.next;
  	while(node)
  	{
  		fp = fopen(node->file_path,"rb");
      	if(fp == NULL)
    	{
        	printf("cannot open this file!\n");
        	continue;
    	}
      	while(!feof(fp))
      	{
			if(fgets(buffer,256,fp) == NULL)
           		break;
        	buffer[strlen(buffer)-1] = '\0';	
			SegmentSentenceMM(buffer,file_nodes);//calling SegmentSentenceMM function Processes punctuation
		}	
		file_nodes++;
		node = node ->next;	
  	}
  	/*
  	*statistics the word numbers of all map and insert the word in spam_map<string,int>
  	*/
  	StatisticsMapWords(file_nodes);
  	
  	/*
  	*printf the word in mapword[]
  	*/
    PrintfMap(file_nodes);
    
    /*
    *printf the word and the word number of spam_map
    */
    PrintfSpam_map();
#if 0
	sortMapByValue(mapword,tVector,file_nodes); //sort by second(value),store the tVector Descending
	FindWord("我们",file_nodes);//find a word whether is in WordDic or not
	MapWordSize();
#endif

	return 0;
}
